/* eslint-disable */
class LwSocket {
  constructor(url, dealMsg) {
    this.url = url;
    this.ws = null;
    this.guid = guid();
    this.lastHeartbeatTime = null;
    this.heartbeatInterval = 10000;
    this.timeout = 30000;
    this.lockReconnect = false; //避免重复连接
    this.currentTryReConnectTime = 0; //当前尝试重连次数
    this.maxTryReConnectTime = 3; //最大尝试重连次数
    this.reConnectTimer = null;
    this.keepAliveTimer = null;
    this.initParam = {};
    this.dealMsg = dealMsg;
    this.msgExpireTime = 60 * 60 * 1000; //消息过期时间
  }
  connect() {
    this.keepAliveTimer && clearInterval(this.keepAliveTimer);
    this.keepAliveTimer = null;
    this.ws = new WebSocket(this.url);
    this.ws.onopen = this.onopen.bind(this);
    this.ws.onmessage = this.onmessage.bind(this);
    this.ws.onclose = this.onclose.bind(this);
    this.ws.onerror = this.onerror.bind(this);
  }
  onopen () {
    var that = this;
    if (that.currentTryReConnectTime > 0) {
      console.log('连接成功');
    }
    that.currentTryReConnectTime = 0;
    that.lastHeartbeatTime = new Date().getTime();
    //传递身份标识及其他
    that.send(JSON.stringify(extend(true, {
      "guid": that.guid,
      "timeout": that.timeout
    }, that.initParam)));
    //启动心跳
    that.keepAliveTimer = setInterval(function () {
      that.keepAlive();
    }, that.heartbeatInterval);
  }
  onmessage (evt) {
    var that = this;
    that.lastHeartbeatTime = new Date().getTime();
    if ("heartbeat" != evt.data) {
      if (isJSON(evt.data)) {
        var msg = JSON.parse(evt.data);
        if (new Date().getTime() - msg.createTime > that.msgExpireTime) { //消息已过期
          return;
        }
        this.dealMsg && that.dealMsg(msg);
      } else {
        this.dealMsg && that.dealMsg(evt.data);
      }
    }
  }
  onclose (evt) {
    this.reConnect();
  }
  onerror (evt) {
    this.reConnect();
  }
  send (message) {
    if (typeof message == 'string' && message.length > 0 && this.ws) {
      this.ws.send(message);
    }
  }
  reConnect () {
    var that = this;
    if (that.lockReconnect) {
      return;
    }
    that.lockReconnect = true;
    that.reConnectTimer && clearTimeout(that.reConnectTimer);
    that.reConnectTimer = null;
    that.ws = null;
    if (that.currentTryReConnectTime < that.maxTryReConnectTime) {
      this.reConnectTimer = setTimeout(function () {
        that.guid = guid();
        that.currentTryReConnectTime++;
        that.connect();
        console.log("第" + that.currentTryReConnectTime + "次重连");
        that.lockReconnect = false;
      }, 3 * 1000);
    } else {
      that.currentTryReConnectTime = 0;
      that.lockReconnect = false;
      that.reConnect();
    }
  }
  close () {
    this.ws.onclose = '';
    this.ws.close();
  }
  keepAlive () {
    var that = this;
    if (new Date().getTime() - that.lastHeartbeatTime > that.timeout) {
      that.ws.close();
    } else {
      that.send("heartbeat");
    }
  }
}


function guid() {
  function S4() {
    return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
  }
  return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
}

var extend = (function () {
  var isObjFunc = function (name) {
    var toString = Object.prototype.toString
    return function () {
      return toString.call(arguments[0]) === '[object ' + name + ']'
    }
  }
  var isObject = isObjFunc('Object'),
    isArray = isObjFunc('Array'),
    isBoolean = isObjFunc('Boolean')
  return function extend() {
    var index = 0,
      isDeep = false,
      obj, copy, destination, source, i
    if (isBoolean(arguments[0])) {
      index = 1
      isDeep = arguments[0]
    }
    for (i = arguments.length - 1; i > index; i--) {
      destination = arguments[i - 1]
      source = arguments[i]
      if (isObject(source) || isArray(source)) {
        //console.log(source)
        for (var property in source) {
          obj = source[property]
          if (isDeep && (isObject(obj) || isArray(obj))) {
            copy = isObject(obj) ? {} : []
            var extended = extend(isDeep, copy, obj)
            destination[property] = extended
          } else {
            destination[property] = source[property]
          }
        }
      } else {
        destination = source
      }
    }
    return destination
  }
})();

function isJSON(str) {
  if (typeof str == 'string') {
    try {
      var obj = JSON.parse(str);
      return (typeof obj == 'object' && obj);
    } catch (e) {
      return false;
    }
  } else {
    return false;
  }
}

export default LwSocket;
